package org.zoomdev.zoom.dao.executors;

import org.zoomdev.zoom.dao.ConnectionExecutor;
import org.zoomdev.zoom.dao.ResultSetParser;
import org.zoomdev.zoom.dao.ResultSetVisitor;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public final class ConnectionExecutors {


    public static <T> T query(Connection connection, ResultSetParser parser, String sql, Object... args) throws SQLException {
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            prepare(ps, args);
            try (ResultSet rs = ps.executeQuery()) {
                return (T) parser.fromResultSet(rs);
            }
        }
    }

    public static void prepare(PreparedStatement ps, Object[] args) throws SQLException {
        for (int i = 1, c = args.length + 1; i < c; ++i) {
            ps.setObject(i, args[i - 1]);
        }
    }

    public static void visit(Connection connection, ResultSetVisitor visitor, String sql, Object... args) throws SQLException {
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            prepare(ps, args);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    visitor.visit(rs);
                }
            }
        }
    }

    public static int executeUpdate(Connection connection, String sql, Object... args) throws SQLException {
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            prepare(ps, args);
            return ps.executeUpdate();
        }
    }

    public static ConnectionExecutor getQueryExecutor(ResultSetParser parser, String sql, Object... args) {
        return connection -> {
            try (PreparedStatement ps = connection.prepareStatement(sql)) {
                prepare(ps, args);
                try (ResultSet rs = ps.executeQuery()) {
                    return parser.fromResultSet(rs);
                }
            }
        };
    }

}
